home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.0 SDK / Sample Code / CloseViewMP ƒ / CloseViewMP.c next >
Encoding:
C/C++ Source or Header  |  1999-08-03  |  11.5 KB  |  583 lines  |  [TEXT/CWIE]

  1. /**\
  2. |**|    CloseViewMP.c
  3. \**/
  4.  
  5. #include "CloseViewMP.h"
  6.  
  7. // typdef's, struct's, define's, enum's, etc.
  8.  
  9. #define kMPStackSize 0        // use default stack size
  10. #define kMPTaskOptions 0    // use no options
  11.  
  12. typedef struct MyTaskStruct {
  13.     MPTaskID        fTaskID;
  14.     MPTaskWeight    fWeight;
  15. }MyTaskRec,*MyTaskPtr,**MyTaskHdl;
  16.  
  17. typedef struct MyGDInfo {
  18.     GDHandle        fGDHdl;
  19.     PixMapHandle    fPixMapHdl;
  20.     Ptr                fBaseAddr;
  21.     Rect            fRect;
  22. }MyGDInfoRec,*MyGDInfoPtr,**MyGDInfoHdl;
  23.  
  24. // external globals
  25.  
  26. UInt32        gMag = 1;
  27.  
  28. // local (static) globals & const
  29.  
  30. static Boolean         gPaused = false;
  31. static Boolean         gLoop = true;
  32.  
  33. #if !SMP_TEST
  34. static MPQueueID         gNotificationQueueID;
  35. static MyTaskRec         gMyTaskRec;
  36. static MPSemaphoreID    gSemaphoreID;
  37. #endif !SMP_TEST
  38.  
  39. static MenuHandle gContextualMenuHdl = nil;
  40.  
  41. static const SInt16 gMags[] = {25,50,100,200,400,800,1600,3200,6400,9999};
  42.  
  43. static Point gMidPoint = {-1,-1};
  44.  
  45. static Rect gSrcRect = {-1,-1,-1,-1};
  46. static Rect gDstRect = {-1,-1,-1,-1};
  47.  
  48. static PixMapHandle gSrcPixMapHdl = nil;
  49. static PixMapHandle gDstPixMapHdl = nil;
  50.  
  51. static Ptr gSrcBaseAddr = nil;
  52. static Ptr gDstBaseAddr = nil;
  53.  
  54. static MyGDInfoRec gMyGDInfoRec[8];    // nobody's got more than 8 monitors
  55.  
  56. // local function prototypes
  57. static OSStatus MyTask(void* pMyTaskPtr);
  58. static void Blit_All(void);
  59. static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect);
  60.  
  61. static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect);
  62. static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2);
  63. static void Set_Rect(
  64.     Rect *r,
  65.     const short pLeft,
  66.     const short pTop,
  67.     const short pRight,
  68.     const short pBottom);
  69.  
  70. static void Offset_Rect(Rect *r,const short pDh,const short pDv);
  71.  
  72. static SInt16 random();
  73.  
  74. #define ABS(x) ((x) < 0 ? -(x) : (x))
  75.  
  76. // local functions
  77.  
  78. /**\
  79. |**|    Initialize everything for CloseViewMP, make sure we can run
  80. \**/
  81.  
  82. OSStatus CVMP_Init(UInt32 pMag)
  83. {
  84.     OSStatus    error;
  85.  
  86.     if (!MPLibraryIsLoaded())
  87.         return kMPInsufficientResourcesErr;
  88.  
  89.     CVMP_Reset();
  90.  
  91.     // Initialize remaining globals
  92.     gNotificationQueueID = NULL;
  93.     gMag = pMag;
  94.  
  95.     // create the notification queue            
  96.     error = MPCreateQueue(&gNotificationQueueID);
  97.     if (error != noErr)
  98.         return error;
  99.  
  100.     // create the task
  101.     {
  102.         gMyTaskRec.fWeight = 100;
  103.  
  104. #    if !SMP_TEST
  105.         error = MPCreateTask(MyTask, &gMyTaskRec,    // task entry point & parameter
  106.             kMPStackSize, gNotificationQueueID,        // stack size & notification queue ID
  107.             &gMyTaskRec, NULL, kMPTaskOptions,        // Notify params 1 & 2 and task options
  108.             &gMyTaskRec.fTaskID);                    // task id
  109.         if (error != noErr)
  110.         {
  111.             DebugStr("\p|CVMP_Init-F-MPCreateTask error.;g");
  112.             return error;
  113.         }
  114.  
  115.         error = MPSetTaskWeight(gMyTaskRec.fTaskID,gMyTaskRec.fWeight);
  116.         if (error != noErr)
  117.         {
  118.             DebugStr("\p|CVMP_Init-F-MPSetTaskWeight error.;g");
  119.             return error;
  120.         }
  121.  
  122.         // create the work semaphore            
  123.         error = MPCreateSemaphore(2, 0, &gSemaphoreID);
  124.         if (error != noErr)
  125.         {
  126.             DebugStr("\p|CVMP_Init-F-MPCreateSemaphore error.;g");
  127.             return error;
  128.         }
  129. #    endif !SMP_TEST
  130.     }
  131.  
  132. //    gContextualMenuHdl = GetMenu(mWeightMenu);
  133. //    InsertMenu(gContextualMenuHdl, -1);
  134.  
  135.     return error;
  136. }    // CVMP_Init
  137.  
  138. /**\
  139. |**|    Cleanup everything
  140. \**/
  141.  
  142. void CVMP_Term(void)
  143. {
  144.     OSStatus error;
  145.  
  146.     gPaused = gLoop = false;
  147.  
  148.     if (gMyTaskRec.fTaskID != NULL)
  149.     {
  150.         // terminate this task
  151.         error = MPTerminateTask(gMyTaskRec.fTaskID, kMPTaskAbortedErr);
  152. //        if (error != noErr)
  153. //            DebugStr("\p|CVMP_Term-F-MPTerminateTask error.;");
  154.  
  155.         // Now wait for notification that this task has terminated
  156.         while ((error = MPWaitOnQueue(gNotificationQueueID,
  157.             NULL, NULL, NULL, kDurationImmediate)) == noErr)
  158.         {
  159.             if (gMyTaskRec.fTaskID != NULL)
  160.                 gMyTaskRec.fTaskID = NULL;
  161.         }
  162.     }
  163.     // delete the notification queue
  164.     if (gNotificationQueueID != NULL)
  165.     {
  166.         MPDeleteQueue(gNotificationQueueID);
  167.         gNotificationQueueID = NULL;
  168.     }
  169. }
  170.  
  171. /**\
  172. |**|    Handle a null event
  173. \**/
  174.  
  175. void CVMP_DoNull(void)
  176. {
  177.     CVMP_Reset();
  178. # if SMP_TEST
  179.     gLoop = false;
  180.     MyTask((void*) &gMyTaskRec);
  181. # else
  182. //    MPYield();
  183. # endif SMP_TEST
  184. }
  185.  
  186. /**\
  187. |**|    Handle a mouse down event
  188. \**/
  189.  
  190. void CVMP_DoClick(const EventRecord *pEventPtr)
  191. {
  192.     Point where = pEventPtr->where;
  193.  
  194.     GlobalToLocal(&where);
  195.  
  196.     SysBeep(15);
  197. }
  198.  
  199. /**\
  200. |**|    set mag
  201. \**/
  202.  
  203. UInt16 CVMP_SetMag(UInt16 pMag)
  204. {
  205.     UInt16 result = gMag;
  206.     gMag = pMag;
  207.  
  208.     CVMP_Reset();
  209.  
  210.     return result;
  211. }
  212.  
  213. /**\
  214. |**|    get mag
  215. \**/
  216.  
  217. UInt16 CVMP_GetMag(void)
  218. {
  219.     return gMag;
  220. }
  221.  
  222. /**\
  223. |**|    set weight
  224. \**/
  225.  
  226. void CVMP_SetWeight(UInt16 pIndex)
  227. {
  228.     if ((pIndex > 0) && (pIndex <= 10))
  229.     {
  230.         OSErr error;
  231.  
  232.         gMyTaskRec.fWeight = gMags[pIndex];
  233.  
  234.         error = MPSetTaskWeight(gMyTaskRec.fTaskID, gMyTaskRec.fWeight);
  235.         if (error != noErr)
  236.             DebugStr("\p|CVMP_SetMag-F-MPSetTaskWeight error.;g");
  237.     }
  238.     else
  239.         SysBeep(15);
  240. }
  241.  
  242. void CVMP_SetMidPoint(Point pPoint)
  243. {
  244.     if (gWindowPtr && !EqualPt(pPoint,gMidPoint))
  245.     {
  246.         gMidPoint = pPoint;
  247.  
  248.         CVMP_Reset();
  249.     }
  250. }
  251.  
  252. /**\
  253. |**|    Reset the mag info
  254. \**/
  255.  
  256. void CVMP_Reset(void)
  257. {
  258.     GDHandle    nthDevice;
  259.     UInt32        index = 0;
  260.  
  261.     gPaused = true;                // pause blitter
  262.     gDstRect = gWindowRect;
  263.  
  264.     for (nthDevice = DMGetFirstScreenDevice(true);nthDevice;
  265.         nthDevice = DMGetNextScreenDevice(nthDevice,true))
  266.     {
  267.         gMyGDInfoRec[index].fGDHdl = nthDevice;
  268.         gMyGDInfoRec[index].fPixMapHdl = (*nthDevice)->gdPMap;
  269.         gMyGDInfoRec[index].fBaseAddr = GetPixBaseAddr(gMyGDInfoRec[index].fPixMapHdl);
  270.         gMyGDInfoRec[index].fRect = (*nthDevice)->gdRect;
  271.         index++;
  272.     }
  273.  
  274.     // zero the rest of the records
  275.     for (;index < 8;index++)
  276.     {
  277.         gMyGDInfoRec[index].fGDHdl = nil;
  278.         gMyGDInfoRec[index].fPixMapHdl = nil;
  279.         gMyGDInfoRec[index].fBaseAddr = nil;
  280.     }
  281.     gLoop = true;
  282.     if (gWindowPtr)
  283.     {    // if the window is unobscured
  284.         static RgnHandle visRgn = nil;
  285.  
  286.         if (!visRgn)
  287.             visRgn = NewRgn();
  288.  
  289.         if (visRgn)
  290.         {
  291.             RgnHandle contRgn = ((WindowPeek) gWindowPtr)->contRgn;
  292.  
  293.             CopyRgn(gWindowPtr->visRgn,visRgn);
  294.  
  295.             OffsetRgn(visRgn,
  296.                 (*contRgn)->rgnBBox.left - (*visRgn)->rgnBBox.left,
  297.                 (*contRgn)->rgnBBox.top - (*visRgn)->rgnBBox.top);
  298.  
  299.             if (EqualRgn(visRgn,contRgn))
  300.                 gPaused = false;    // unpause blitter
  301.         }
  302.     }
  303. }
  304.  
  305. /**\
  306. |**|    This causes the blit task to break out of its slumber.
  307. \**/
  308.  
  309. void CVMP_Update(void)
  310. {
  311. #if !SMP_TEST
  312.     MPSignalSemaphore(gSemaphoreID);
  313. #endif
  314. }
  315.  
  316. /**\
  317. |**|    set & return the paused state
  318. \**/
  319.  
  320. extern Boolean CVMP_Pause(Boolean pPaused)
  321. {
  322.     Boolean result = gPaused;
  323.     gPaused = pPaused;
  324.  
  325.     return result;
  326. }
  327.  
  328. /**\
  329. |**|    This is the MP task entrypoint
  330. \**/
  331.  
  332. static OSStatus MyTask(void* pMyTaskPtr)
  333. {
  334.     Point    oldmloc;
  335.     Point    mloc;
  336.     (pMyTaskPtr);    // #pragma unused (pMyTaskPtr)
  337.  
  338.     //    Blit the data periodically but at a low refresh rate. the main task
  339.     //    will signal if it has demand blitting to do.
  340.     do {
  341.         Blit_All();
  342.         
  343.         do {
  344.             int i;
  345.             
  346.             for (i=0; i<12; i++)
  347.             {
  348. #if !SMP_TEST
  349.                 (void) MPWaitOnSemaphore(gSemaphoreID, 33 * kDurationMillisecond);
  350. #endif !SMP_TEST
  351.                 mloc = LMGetMouseLocation();
  352.                 if (oldmloc.v != mloc.v || oldmloc.h != mloc.h)
  353.                 {
  354.                 oldmloc = mloc;
  355.                 break;
  356.                 }
  357.             }
  358.  
  359.         } while (gPaused && gLoop);
  360.     } while (gLoop);
  361.  
  362.     return noErr;
  363. }
  364.  
  365. /**\
  366. |**|    Blit All
  367. \**/
  368.  
  369. static void Blit_All(void)
  370. {
  371.     SInt32 srcIndex,dstIndex;
  372.  
  373.     gMidPoint = *(Point*)0x0830;
  374.  
  375.     for (dstIndex = 0;dstIndex < 8;dstIndex++)
  376.     {
  377.         if (gMyGDInfoRec[dstIndex].fGDHdl)
  378.         {
  379.             Rect dstRect = gDstRect;
  380.  
  381.             if (Intersect_Rects(&gMyGDInfoRec[dstIndex].fRect,&dstRect))
  382.             {
  383.                 gDstPixMapHdl = gMyGDInfoRec[dstIndex].fPixMapHdl;
  384.                 gDstBaseAddr = gMyGDInfoRec[dstIndex].fBaseAddr;
  385.  
  386.                 Set_Rect(&gSrcRect,0,0,
  387.                     ((dstRect.right - dstRect.left) / gMag) + 1,
  388.                     ((dstRect.bottom - dstRect.top) / gMag) + 1);
  389.  
  390.                 Offset_Rect(&gSrcRect,
  391.                     gMidPoint.h - ((gSrcRect.left + gSrcRect.right) >> 1),
  392.                     gMidPoint.v - ((gSrcRect.top + gSrcRect.bottom) >> 1));
  393.  
  394.                 for (srcIndex = 0;srcIndex < 8;srcIndex++)
  395.                 {
  396.                     if (gMyGDInfoRec[srcIndex].fGDHdl)
  397.                     {
  398.                         Rect srcRect = gSrcRect;
  399.  
  400. //                        if (Intersect_Rects(&gMyGDInfoRec[srcIndex].fRect,&srcRect))
  401.                         if (Point2_In_Rect(gMidPoint.h,gMidPoint.v,&gMyGDInfoRec[srcIndex].fRect))
  402.                         {
  403.                             gSrcPixMapHdl = gMyGDInfoRec[srcIndex].fPixMapHdl;
  404.                             gSrcBaseAddr = gMyGDInfoRec[srcIndex].fBaseAddr;
  405.  
  406.                             Blit_One(&gSrcRect,&dstRect);
  407.                         }
  408.                     }
  409.                 }
  410.             }
  411.         }
  412.     }
  413. }
  414.  
  415. static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect)
  416. {
  417.     if (gSrcPixMapHdl && gDstPixMapHdl)
  418.     {
  419.         Rect         srcBounds = (*gSrcPixMapHdl)->bounds;
  420.         UInt32         srcBytesPerPixel = (*gSrcPixMapHdl)->pixelSize / 8;
  421.         UInt32         srcSkip = (*gSrcPixMapHdl)->rowBytes & 0x3FFF;
  422.         Ptr         srcBase = gSrcBaseAddr +
  423.                         (srcSkip * (pSrcRect->top - srcBounds.top)) +
  424.                         ((pSrcRect->left - srcBounds.left) * srcBytesPerPixel);
  425.  
  426.         Rect         dstBounds = (*gDstPixMapHdl)->bounds;
  427.         UInt32         dstBytesPerPixel = (*gDstPixMapHdl)->pixelSize / 8;
  428.         UInt32         dstSkip = (*gDstPixMapHdl)->rowBytes & 0x3FFF;
  429.         Ptr         dstBase = gDstBaseAddr +
  430.                         (dstSkip * (pDstRect->top - dstBounds.top)) +
  431.                         ((pDstRect->left - dstBounds.left) * dstBytesPerPixel);
  432.  
  433.         SInt32 dstRow,dstCol,srcRow,srcCol,magRow,magCol;
  434.  
  435.         magRow = 0;
  436.         srcRow = pSrcRect->top;
  437.         for (dstRow = pDstRect->top;dstRow < pDstRect->bottom;dstRow++)
  438.         {
  439.             Ptr srcPtr = srcBase,dstPtr = dstBase;
  440.             UInt32    color32 = -1;
  441.             UInt16    color16 = -1;
  442.             UInt8     color8 = -1;
  443.  
  444.             magCol = 0;
  445.             srcCol = pSrcRect->left;
  446.             for (dstCol = pDstRect->left;dstCol < pDstRect->right;dstCol++)
  447.             {
  448. //                Boolean draw_flag = true;
  449.                 if (!magCol)
  450.                 {
  451.                     if ((srcRow >= srcBounds.top) &&
  452.                         (srcRow < srcBounds.bottom) &&
  453.                         (srcCol >= srcBounds.left) &&
  454.                         (srcCol < srcBounds.right))
  455.                     {
  456.                         color32 = *(UInt32*) srcPtr;
  457.                         color16 = color32 & 0xFFFF;
  458.                         color8 = color16 & 0xFF;
  459.                     }
  460.                     else
  461.                         //draw_flag = false;
  462.                         color32 = color16 = color8 = 0;
  463.  
  464.                     srcPtr += srcBytesPerPixel;
  465.                     srcCol++;
  466.                 }
  467.  
  468.                 if ((dstRow >= dstBounds.top) &&
  469.                     (dstRow < dstBounds.bottom) &&
  470.                     (dstCol >= dstBounds.left) &&
  471.                     (dstCol < dstBounds.right))
  472.                 {
  473.                     switch (dstBytesPerPixel)
  474.                     {
  475.                         case 1:        // 256 colors
  476.                             *dstPtr = color8;
  477.                             break;
  478.                         case 2:    // thousand colors
  479.                             *(UInt16*) dstPtr = color16;
  480.                             break;
  481.                         case 4:    // million colors
  482.                             *(UInt32*) dstPtr = color32;
  483.                             break;
  484.                     }
  485.                 }
  486.                 dstPtr += dstBytesPerPixel;
  487.  
  488.                 magCol++;
  489.                 magCol %= gMag;
  490.             }
  491.             magRow++;
  492.             magRow %= gMag;
  493.             if (!magRow)
  494.             {
  495.                 srcBase += srcSkip;
  496.                 srcRow++;
  497.             }
  498.  
  499.             dstBase += dstSkip;
  500.         }
  501.     }
  502. }
  503.  
  504. /**\
  505. |**|    Test to see if a point is in a rect
  506. \**/
  507.  
  508. static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect)
  509. {
  510.     if (pV < pRect->top)
  511.         return false;
  512.     if (pV >= pRect->bottom)
  513.         return false;
  514.     if (pH < pRect->left)
  515.         return false;
  516.     if (pH >= pRect->right)
  517.         return false;
  518.     return true;
  519. }
  520.  
  521. static void Set_Rect(Rect *r,
  522.     const short pLeft,
  523.     const short pTop,
  524.     const short pRight,
  525.     const short pBottom)
  526. {
  527.     r->top = pTop;
  528.     r->right = pRight;
  529.     r->bottom = pBottom;
  530.     r->left = pLeft;
  531. }
  532.  
  533. /**\
  534. |**|    aBool = SectRect(src1,src2,dstRect);
  535. \**/
  536.  
  537. static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2)
  538. {
  539.     if (pRect2->top < pRect1->top)
  540.         pRect2->top = pRect1->top;
  541.  
  542.     if (pRect2->bottom > pRect1->bottom)
  543.         pRect2->bottom = pRect1->bottom;
  544.  
  545.     if (pRect2->left < pRect1->left)
  546.         pRect2->left = pRect1->left;
  547.  
  548.     if (pRect2->right > pRect1->right)
  549.         pRect2->right = pRect1->right;
  550.  
  551.     if ((pRect2->top < pRect2->bottom) &&
  552.         (pRect2->left < pRect2->right))
  553.         return true;
  554.     else
  555.         return false;
  556. }
  557.  
  558. /**\
  559. |**|    move a rectangle
  560. \**/
  561.  
  562. static void Offset_Rect(Rect *r,const short pDh,const short pDv)
  563. {
  564.     r->top += pDv;
  565.     r->left += pDh;
  566.     r->bottom += pDv;
  567.     r->right += pDh;
  568. }
  569.  
  570. /**\
  571. |**|    generate a random number +/- 32768
  572. \**/
  573.  
  574. static SInt16 random()
  575. {
  576.     static SInt32 state = 314159;
  577.  
  578.     state = ((state * 1103515245) + 12345 ) & 0x7fffffff;
  579.  
  580.     return ((state >> 6) & 0xffff);
  581. }
  582.  
  583.